﻿using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using HBKY.Shop.Common;
using HBKY.Shop.Model.Enum;
using HBKY.Shop.Common.Extension;
using HBKY.Shop.Common.Exceptions;
using HBKY.Shop.Common.Helper;
using HBKY.Shop.Model;
using HBKY.Shop.Common.Redis;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using HBKY.Shop.Common.Constant;

namespace HBKY.Shop.Extensions.Filter
{
    /// <summary>
    /// 全局异常处理
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class ExceptionHandleFilter : ExceptionFilterAttribute
    {
        private readonly IModelMetadataProvider _modelMetadataProvider;
        private readonly ILogger<ExceptionHandleFilter> _logger;
        private readonly IRedisBasketRepository _redisBasketRepository;
        public ExceptionHandleFilter(IRedisBasketRepository redisBasketRepository,IModelMetadataProvider modelMetadataProvider, ILogger<ExceptionHandleFilter> logger)
        {
            _redisBasketRepository = redisBasketRepository;
            _modelMetadataProvider = modelMetadataProvider;
            _logger = logger;
        }

        /// <summary>
        /// 没有处理的异常，就会进来
        /// </summary>
        /// <param name="filterContext"></param>
        public async override Task OnExceptionAsync(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)//异常有没有被处理过
            {
                string controllerName = (string)filterContext.RouteData.Values["controller"];
                string actionName = (string)filterContext.RouteData.Values["action"];
                string errorMsg = filterContext.Exception.Message;
                string msgTemplate = $"在执行 controller[{controllerName}] 的 action[{actionName}] 时产生异常,异常信息:{errorMsg}";
                bool isWriteLog = true; int statusCode = StatusCodeEnum.Status400BadRequest.Key();

                #region 日志分类统一处理

                if (filterContext.Exception is BusinessException)
                {
                    //    //业务异常给出提示语  不记录日志
                    isWriteLog = false;
                    statusCode = StatusCodeEnum.Status1101BusinessError.Key();
                }
                else if (filterContext.Exception is ArgumentException)
                {
                    errorMsg = MessageModel.ServerConnectionError;
                    statusCode = StatusCodeEnum.Status1102ArgumentError.Key();
                }
                else if (filterContext.Exception is Exception)
                {
                    errorMsg = MessageModel.ServerConnectionError;
                }
                else
                {
                    errorMsg = MessageModel.ServerConnectionError;
                    statusCode = StatusCodeEnum.Status400BadRequest.Key();
                }

                #endregion

                //区分异常是否记录日志
                if (isWriteLog)
                {
                    try
                    {
                        Dictionary<string, string> logerDic = new Dictionary<string, string>()
                    {
                        {"项目名称" , Appsettings.Option("Startup", "ApiName") },
                        {"日志级別" , LogLevel.Error.ToString()},
                        {"链路标识" , System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString()},
                        {"异常时间" , DateTime.Now.ToString(DateTimeFormatConst.yyyy_MM_ddHHmmss)},
                        {"日志信息" , msgTemplate },
                        {"堆栈信息" , filterContext.Exception.StackTrace}
                    };
                        if (Appsettings.Option("DingTalkConfig", "Enabled").ObjToBool())
                            await _redisBasketRepository.ListLeftPushAsync(Appsettings.Option("DingTalkConfig", "LogQueue"), JsonConvert.SerializeObject(logerDic));
                    }
                    catch
                    {
                    }
                    finally
                    {
                        _logger.LogError(filterContext.Exception, msgTemplate);
                    }
                }
                Console.WriteLine(filterContext.Exception.Message);
                //不是正式环境提示语还是抛出异常信息
                if (!EnvHelper.IsOnline) errorMsg = filterContext.Exception.Message;

                //处理 http请求的状态码
                //filterContext.HttpContext.Response.StatusCode = statusCode;

                //api 不区分处理是不是 ajax请求
                filterContext.Result = new JsonResult(
                    new ResponseMessage<string>()
                    {
                        Code = statusCode,
                        Message = errorMsg,
                        Success = false
                    });
                filterContext.ExceptionHandled = true;
            }
        }
    }
}
